section .asm 

extern no_interrupt_handler
extern int21h_handler
extern isr80h_handler

global idt_load
global int21h
global enable_interrupts
global disable_interrupts
global no_interrupt
global isr80h_wrapper

enable_interrupts:
    sti
    ret 

disable_interrupts:
    cli
    ret

idt_load:
    push ebp         ; push base pointer
    mov ebp, esp     ; move stack pointer into a base pointer
    mov ebx, [ebp+8] ; 
    lidt [ebx]

    pop ebp   
    ret

; keyboard interrupt
int21h:
    ; PUSHAD - pushes the contents of the general-purpose registers into a stack
    ;          order: EAX, ECX, EDX, EBX, EBP, ESP (original value), EBP, ESI, EDI

    pushad
    call int21h_handler
    popad 
    iret ; interrupts should end with IRET, not RET

no_interrupt:
    ; PUSHAD - pushes the contents of the general-purpose registers into a stack
    ;          order: EAX, ECX, EDX, EBX, EBP, ESP (original value), EBP, ESI, EDI

    pushad
    call no_interrupt_handler
    popad 
    iret ; interrupts should end with IRET, not RET

isr80h_wrapper:
    ; PUSHAD - pushes the contents of the general-purpose registers into a stack
    ;          order: EAX, ECX, EDX, EBX, EBP, ESP (original value), EBP, ESI, EDI

    pushad

    ; Interrupt frame end  
    push esp ; push the stack pointer: we are pointing at the end of interrupt frame
    push eax ; push the command code
    call isr80h_handler ; call function isr80h_handler(command_code, interrupt_frame)
    mov DWORD [tmp_res], eax ; eax stores return value

    add esp, 8 ; restore the stack, you also can call 'pop ebx' twice

    popad ; restore the general-purpose registers
    mov eax, [tmp_res]
    iretd

section .data
; Stores the resurn results from isr80h_handler
tmp_res: dd 0